# -*- coding: utf-8 -*-
import hashlib
import json

import requests
from django.conf import settings

from common.chase import db as chase_db
from common.mch import db as mch_db
from common.mch.model import MCH_TYPE
from common.order import db as order_db
from common.order.model import PAY_STATUS
from common.utils import track_logging
from common.utils.exceptions import ParamError, AuthenticateError

_LOGGER = track_logging.getLogger(__name__)

_HANDLER_DCT = {
    MCH_TYPE.WITCH: settings.PAY_CHASE_URL_WITCH,
    MCH_TYPE.LOKI: settings.PAY_CHASE_URL_LOKI,
    MCH_TYPE.KS: settings.PAY_CHASE_URL_DWC,
    MCH_TYPE.ZS: settings.PAY_CHASE_URL_ZS,
}


def _generate_sign(mch_id, params):
    mch_account = mch_db.get_account(mch_id)
    if not mch_account:
        raise AuthenticateError('mch_id invalid')
    s = ''
    for k in sorted(params.keys()):
        s += '%s=%s&' % (k, params[k])
    s += 'key=%s' % mch_account.api_key
    m = hashlib.md5()
    m.update(s.encode('utf8'))
    sign = m.hexdigest().upper()
    return sign


def create_chase_charge(params):
    mch_id = int(params["mch_id"])
    desc = params["desc"]
    params['sign'] = _generate_sign(mch_id, params)
    _LOGGER.info("chase_charge create params: %s", params)
    headers = {'Content-Type': 'application/json'}
    response = requests.post(_HANDLER_DCT.get(mch_id), data=json.dumps(params), headers=headers, timeout=10)
    _LOGGER.info("chase_charge resp data: %s", response.text)
    try:
        response.raise_for_status()
    except (requests.exceptions.HTTPError, requests.exceptions.Timeout) as e:
        _LOGGER.warn('chase_charge status_code: %s, err_msg: %s', e.response.status_code, e.response.text)
        raise ParamError(e.response.text)

    pay_id = json.loads(response.text)['data']['order_id']

    pay = order_db.get_pay(pay_id)
    if not pay:
        raise ParamError('pay_id: %s invalid' % pay_id)
    if pay.status != PAY_STATUS.READY:
        raise ParamError('pay %s has been processed' % pay_id)

    params['id'] = pay_id
    params['out_trade_no'] = pay.out_trade_no

    return chase_db.create_order(params)
